package com.geezdata.cps.ttk_admin.api.config;

import java.util.List;
import java.util.stream.Collectors;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import com.geezdata.cps.base.constant.ShiroConstants;
import com.geezdata.cps.ttk.common.vo.UserResVO;
import com.geezdata.cps.ttk.query.query.UserService;

public class UserRealm extends AuthorizingRealm{
	private static final Logger logger = LoggerFactory.getLogger(UserRealm.class);
	@Autowired
	private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String currentLoginName = (String)principals.getPrimaryPrincipal();
        
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if(ShiroConstants.USER_SCHEDULE.equals(currentLoginName)) {
            authorizationInfo.addRole(ShiroConstants.ROLE_ADMIN);
            return authorizationInfo;
        }
        
        logger.info("对用户[" + currentLoginName + "]进行授权验证..###【开始认证[SessionId]】" 
        		+ SecurityUtils.getSubject().getSession().getId());
        

        UserResVO userVO = userService.getUserDetailByUserName(currentLoginName, 1);   	
    	if(!CollectionUtils.isEmpty(userVO.getRoleList())) {
			List<String> userRoles = userVO.getRoleList().stream()
    	            .map(userRoleVO -> userRoleVO.getRole().getRoleCode())
    	            .collect(Collectors.toList());
    		logger.info("#######获取角色：{}", userRoles);
    		authorizationInfo.addRoles(userRoles);
    	}
        return authorizationInfo;
    }

    /** 
     * 验证当前登录的Subject
     * LoginController.login()方法中执行Subject.login()时 执行此方法 
     */ 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        String loginName = (String)authcToken.getPrincipal();
        
        SimpleAuthenticationInfo authenticationInfo = null;
        if(ShiroConstants.USER_SCHEDULE.equals(loginName)) {
        	authenticationInfo = new SimpleAuthenticationInfo(ShiroConstants.USER_SCHEDULE, ShiroConstants.USER_SCHEDULE, getName());
        	return authenticationInfo;
        }
        
        logger.info("对用户[" + loginName + "]进行登录验证..###【开始认证[SessionId]】" 
        		+ SecurityUtils.getSubject().getSession().getId());
        
        UserResVO userVO = userService.getUserDetailByUserName(loginName, 1);
        if(userVO == null) {
            throw new UnknownAccountException();//没找到帐号
        }
        
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
        authenticationInfo = new SimpleAuthenticationInfo(
        		userVO.getUserName(), //用户名
        		userVO.getPassword(), //密码
                ByteSource.Util.bytes(userVO.getSalt()),//salt=username+salt,采用明文访问时，不需要此句
                getName()  //realm name
        );
        
        return authenticationInfo;
    }
    
    @Override
	protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)
			throws AuthenticationException {
		String userName = (String) token.getPrincipal();
		if(!ShiroConstants.USER_SCHEDULE.equals(userName)) {
			super.assertCredentialsMatch(token, info);
		}
	}
    
    @Override
	protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
		if(!CollectionUtils.isEmpty(info.getRoles()) && info.getRoles().contains(ShiroConstants.ROLE_ADMIN)) {
			return true;
		}
		
		return super.hasRole(roleIdentifier, info);
	}

	@Override
	protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
		if(!CollectionUtils.isEmpty(info.getRoles()) && info.getRoles().contains(ShiroConstants.ROLE_ADMIN)) {
			return true;
		}
		return super.isPermitted(permission, info);
	}

	@Override
	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		return SecurityUtils.getSubject().getSession().getId();
	}
}